#define _CRT_SECURE_NO_WARNINGS
#include "Contact.h"
#include "SQList.h"
#include <string.h>
#include <stdio.h>
void InitContact(contact* con)
{
	SLInit(con);//在contact.h里就说过，通讯录就是一个线性表，所以这里不需要写新的函数
}
void DestroyContact(contact* con)
{
	SLDestroy(con);
}
void GenderInput(int ret, char* p)//拒绝zzzq，性别只有男性/女性，像那些什么乱七八糟的，比如沃尔玛购物袋、阿帕奇武装直升机，我的数组里也装不下啊
{
	int flag = 1;
	while (flag && ret)
	{
		scanf("%s", p);
		if (strcmp(p, "男性") && strcmp(p, "女性") && strcmp(p, "未知"))
		{
			printf("无效性别，请重新输入:");
		}
		else
		{
			flag = 0;
		}
	}
}
//添加联系人
void AddContact(contact* con)
{
	PeoInfo tmp;
	printf("请输入联系人姓名:");
	scanf("%s", tmp.name);
	int flag = 1;
	printf("请输入联系人性别:（男性/女性/未知）:");
	GenderInput(1, tmp.gender);	
	printf("请输入联系人年龄:");
	scanf("%d", &tmp.age);
	printf("请输入联系人电话号码:");
	scanf("%s", tmp.telephone);
	printf("请输入联系人地址:");
	scanf("%s", tmp.address);
	SLPushBack(con, tmp);
}
int FindByName(contact* con, char target[NAME_MAX])//前文已述，这里需要有针对结构体各个成员进行搜索的函数。此处只实现了最常用、最基础的按名字搜索
{
	int i;
	for (i = 0; i < con->size; i++)
	{
		if (strcmp(con->a[i].name, target) == 0)
		{
			return i;
		}
	}
	return -1;//下标是不会为负数的（毕竟不是Python之类的），返回负数表示找不到
}
//删除联系人
void DelContact(contact* con)
{
	printf("请输入需要删除的联系人姓名：");
	char target[NAME_MAX];
	scanf("%s", target);
	int note = FindByName(con, target);
	if (note >= 0)
	{
		SLErase(con, note);
		printf("已成功删除\n");
	}
	else
	{
		printf("未找到此人,请重新选择\n");
	}
}
//搜寻联系人，如果确有则输出信息
void FindContact(contact* con)
{
	printf("请输入需要查找的联系人姓名：");
	char target[NAME_MAX];
	scanf("%s", target);
	int note = FindByName(con, target);
	if (note >= 0)
	{
		printf("已成功找到该联系人，以下为对方信息：\n");
		printf("联系人：%s\n性别：%s\n年龄：%d\n电话号码：%s\n地址：%s\n", con->a[note].name, con->a[note].gender, con->a[note].age, con->a[note].telephone, con->a[note].address);
	}
	else
	{
		printf("未找到此人,请重新选择\n");
	}
}
//展示所有联系人
void ShowContact(contact* con)//这里总是会有各种各样的显示、对齐问题，等有时间了在摸一下罢
{
	int i;
	printf("已储存全部联系人信息如下：\n%s\t\t\t%s\t%s\t%s\t\t\t%s\n", "姓名", "性别", "年龄", "电话号码", "地址");
	for (i = 0; i < con->size; i++)
	{
		printf("%s\t\t\t%s\t%d\t%s\t\t\t%s\n", con->a[i].name, con->a[i].gender, con->a[i].age, con->a[i].telephone, con->a[i].address);
	}
}
void check(int* ret, char* option)//原本修改信息时是每个都要改，这里加了个自主选择的函数
{
	int flag = 1;
	while (flag)
	{
		printf("请问是/否需要修改联系人%s？（分别用1/0表示是与否）\n", option);
		scanf("%d", ret);
		if (*ret == 1)
		{
			printf("请输入新的联系人%s:", option);
			flag = 0;
		}
		else if(*ret == 0)
		{
			printf("好的，将保持原数据不变\n");
			flag = 0;
		}
		else
		{
			printf("无效输入，请重新选择");
		}
	}
}
//修改联系人
void ModifyContact(contact* con)
{
	printf("请输入需要修改的联系人姓名：\n");
	char target[NAME_MAX];
	scanf("%s", target);
	int note = FindByName(con, target);
	if (note >= 0)
	{
		printf("已成功找到该联系人\n");
	}
	else
	{
		printf("未找到此人,请重新选择\n");
		return;
	}
	int ret = 1;
	check(&ret, "姓名");
	if(ret)
		scanf("%s", con->a[note].name);
	int flag = 1;
	check(&ret, "性别");
	if (ret)
		scanf("%s", con->a[note].gender);
	while (flag && ret)
	{
		if (strcmp(con->a[note].gender, "男性") && strcmp(con->a[note].gender, "女性") && strcmp(con->a[note].gender, "未知"))
		{
			printf("无效性别，请重新输入:");
			scanf("%s", con->a[note].gender);
		}
		else
		{
			flag = 0;
		}
	}
	check(&ret, "年龄");
	if (ret)
		scanf("%d", &con->a[note].age);
	check(&ret, "电话号码");
	if (ret)
		scanf("%s", con->a[note].telephone);
	check(&ret, "地址");
	if (ret)
		scanf("%s", con->a[note].address);
	printf("修改成功");
}
//保存通讯录
void SaveContact(contact* con)//本来想通过保存下来的这个contact.txt文件直接去读信息的，好像认不出。不知道C能不能写csv文件，如果能就十分适合这种使用情况
{
	FILE* pf = fopen("contact.txt", "wb");
	if (pf == NULL) 
	{
		perror("fopen error!\n");
		return;
	}
	//将通讯录数据写⼊⽂件
	for (int i = 0; i < con->size; i++)
	{
		fwrite(con->a + i, sizeof(PeoInfo), 1, pf);
	}
	printf("通讯录数据保存已成功保存在与本程序同文件夹的contact.txt内，请妥善保存！\n");
}
//读取通讯录
void LoadContact(contact* con) {
	FILE* pf = fopen("contact.txt", "rb");
	if (pf == NULL) 
	{
		perror("fopen error!\n");
		return;
	}
	//循环读取⽂件数据
	PeoInfo info;
	while (fread(&info, sizeof(PeoInfo), 1, pf))
	{
		SLPushBack(con, info);
	}
	printf("历史数据导入通讯录成功！\n");
}
void(*p[8])(contact* con) = { NULL,AddContact,DelContact,FindContact,ShowContact,ModifyContact, SaveContact, LoadContact };//通过函数指针在project（）中少写点东西。如果用枚举会更加直观，不过这里也没有那样的必要了
void menu()
{
	printf("——通讯录——\n");
	printf("1.添加  2.删除\n");
	printf("3.查询  4.展示\n");
	printf("5.修改  6.保存\n");
	printf("7.导入历史数据\n");
	printf(" 0.退出通讯录 \n");
	printf("———————\n");
}
void project()
{
	contact con;
	InitContact(&con);
	int opt = 0;
	do
	{
		printf("欢迎使用本通讯录，请选择您的操作：\n");
		menu();
		scanf("%d", &opt);
		if (opt == 1 || opt == 2 || opt == 3 || opt == 4 || opt == 5 || opt == 6 || opt == 7)
		{
			p[opt](&con);
		}
		else if (opt == 0)
		{
			printf("已成功退出，期待您的下一次使用\n");
			break;
		}
		else
		{
			printf("无效输入，请重新选择\n");
		}
	} while (opt);
	DestroyContact(&con);
}